/*!
 * template.js v0.7.1 (https://github.com/yanhaijing/template.js)
 * API https://github.com/yanhaijing/template.js/blob/master/doc/api.md
 * Copyright 2015 yanhaijing. All Rights Reserved
 * Licensed under MIT (https://github.com/yanhaijing/template.js/blob/master/MIT-LICENSE.txt)
 */
/* eslint-disable */
function factory(root) {
	'use strict'
	var o = {
		sTag: '<%', //开始标签
		eTag: '%>', //结束标签
		compress: false, //是否压缩html
		escape: true, //默认输出是否进行HTML转义
		error: function (e) {} //错误回调
	}
	var functionMap = {} //内部函数对象
	//修饰器前缀
	var modifierMap = {
		'': function (param) {
			return nothing(param)
		},
		h: function (param) {
			return encodeHTML(param)
		},
		u: function (param) {
			return encodeURI(param)
		}
	}

	var toString = {}.toString
	var slice = [].slice
	function type(x) {
		if (x === null) {
			return 'null'
		}

		var t = typeof x

		if (t !== 'object') {
			return t
		}

		var c = toString.call(x).slice(8, -1).toLowerCase()
		if (c !== 'object') {
			return c
		}

		if (x.constructor == Object) {
			return c
		}

		return 'unknown'
	}

	function isObject(obj) {
		return type(obj) === 'object'
	}
	function isFunction(fn) {
		return type(fn) === 'function'
	}
	function isString(str) {
		return type(str) === 'string'
	}
	function extend() {
		var target = arguments[0] || {}
		var arrs = slice.call(arguments, 1)
		var len = arrs.length

		for (var i = 0; i < len; i++) {
			var arr = arrs[i]
			for (var name in arr) {
				target[name] = arr[name]
			}
		}
		return target
	}
	function clone() {
		var args = slice.call(arguments)
		return extend.apply(null, [{}].concat(args))
	}
	function nothing(param) {
		return param
	}
	function encodeHTML(source) {
		return String(source)
			.replace(/&/g, '&amp;')
			.replace(/</g, '&lt;')
			.replace(/>/g, '&gt;')
			.replace(/\\/g, '&#92;')
			.replace(/"/g, '&quot;')
			.replace(/'/g, '&#39;')
	}
	function compress(html) {
		return html.replace(/\s+/g, ' ').replace(/<!--[\w\W]*?-->/g, '')
	}
	function consoleAdapter(cmd, msg) {
		typeof console !== 'undefined' && console[cmd] && console[cmd](msg)
	}
	function handelError(e) {
		var message = 'template.js error\n\n'

		for (var key in e) {
			message += '<' + key + '>\n' + e[key] + '\n\n'
		}
		message += '<message>\n' + e.message + '\n\n'
		consoleAdapter('error', message)

		o.error(e)
		function error() {
			return 'template.js error'
		}
		error.toString = function () {
			return '__code__ = "template.js error"'
		}
		return error
	}
	function parse(tpl, opt) {
		var code = ''
		var sTag = opt.sTag
		var eTag = opt.eTag
		var escape = opt.escape
		function parsehtml(line) {
			// 单双引号转义，换行符替换为空格
			line = line.replace(/('|")/g, '\\$1')
			var lineList = line.split('\n')
			var code = ''
			for (var i = 0; i < lineList.length; i++) {
				code += ';__code__ += ("' + lineList[i] + (i === lineList.length - 1 ? '")\n' : '\\n")\n')
			}
			return code
		}
		function parsejs(line) {
			//var reg = /^(:?)(.*?)=(.*)$/;
			var reg = /^(?:=|(:.*?)=)(.*)$/
			var html
			var arr
			var modifier

			// = := :*=
			// :h=123 [':h=123', 'h', '123']
			if ((arr = reg.exec(line))) {
				html = arr[2] // 输出
				if (Boolean(arr[1])) {
					// :开头
					modifier = arr[1].slice(1)
				} else {
					// = 开头
					modifier = escape ? 'h' : ''
				}

				return (
					';__code__ += __modifierMap__["' +
					modifier +
					'"](typeof (' +
					html +
					') !== "undefined" ? (' +
					html +
					') : "")\n'
				)
			}

			//原生js
			return ';' + line + '\n'
		}

		var tokens = tpl.split(sTag)

		for (var i = 0, len = tokens.length; i < len; i++) {
			var token = tokens[i].split(eTag)

			if (token.length === 1) {
				code += parsehtml(token[0])
			} else {
				code += parsejs(token[0], true)
				if (token[1]) {
					code += parsehtml(token[1])
				}
			}
		}
		return code
	}
	function compiler(tpl, opt) {
		var mainCode = parse(tpl, opt)

		var headerCode =
			'\n' +
			'    var html = (function (__data__, __modifierMap__) {\n' +
			'        var __str__ = "", __code__ = "";\n' +
			'        for(var key in __data__) {\n' +
			'            __str__+=("var " + key + "=__data__[\'" + key + "\'];");\n' +
			'        }\n' +
			'        eval(__str__);\n\n'

		var footerCode =
			'\n' + '        ;return __code__;\n' + '    }(__data__, __modifierMap__));\n' + '    return html;\n'

		var code = headerCode + mainCode + footerCode
		code = code.replace(/[\r]/g, ' ') // ie 7 8 会报错，不知道为什么
		try {
			var Render = new Function('__data__', '__modifierMap__', code)
			Render.toString = function () {
				return mainCode
			}
			return Render
		} catch (e) {
			e.temp = 'function anonymous(__data__, __modifierMap__) {' + code + '}'
			throw e
		}
	}
	function compile(tpl, opt) {
		opt = clone(o, opt)

		try {
			var Render = compiler(tpl, opt)
		} catch (e) {
			e.name = 'CompileError'
			e.tpl = tpl
			e.render = e.temp
			delete e.temp
			return handelError(e)
		}

		function render(data) {
			data = clone(functionMap, data)
			try {
				var html = Render(data, modifierMap)
				html = opt.compress ? compress(html) : html
				return html
			} catch (e) {
				e.name = 'RenderError'
				e.tpl = tpl
				e.render = Render.toString()
				return handelError(e)()
			}
		}

		render.toString = function () {
			return Render.toString()
		}
		return render
	}
	function template(tpl, data) {
		if (typeof tpl !== 'string') {
			return ''
		}

		var fn = compile(tpl)
		if (!isObject(data)) {
			return fn
		}

		return fn(data)
	}

	template.config = function (option) {
		if (isObject(option)) {
			o = extend(o, option)
		}
		return clone(o)
	}

	template.registerFunction = function (name, fn) {
		if (!isString(name)) {
			return clone(functionMap)
		}
		if (!isFunction(fn)) {
			return functionMap[name]
		}

		return (functionMap[name] = fn)
	}
	template.unregisterFunction = function (name) {
		if (!isString(name)) {
			return false
		}
		delete functionMap[name]
		return true
	}

	template.registerModifier = function (name, fn) {
		if (!isString(name)) {
			return clone(modifierMap)
		}
		if (!isFunction(fn)) {
			return modifierMap[name]
		}

		return (modifierMap[name] = fn)
	}
	template.unregisterModifier = function (name) {
		if (!isString(name)) {
			return false
		}
		delete modifierMap[name]
		return true
	}

	template.__encodeHTML = encodeHTML
	template.__compress = compress
	template.__handelError = handelError
	template.__compile = compile
	template.version = '0.7.1'
	return template
}

var template = factory(typeof window !== 'undefined' ? window : globalThis);
export default template
